/**
 * @author Caius
 * @description
 * @version 1.0
 * @since Created in 2024-12-30
 */

package com.itsense.stock.service.Impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itsense.stock.constant.StockConstant;
import com.itsense.stock.mapper.*;
import com.itsense.stock.pojo.domain.*;
import com.itsense.stock.pojo.entity.*;
import com.itsense.stock.pojo.vo.PermissionUpdateVo;
import com.itsense.stock.service.UserService;
import com.itsense.stock.utils.IdWorker;
import com.itsense.stock.utils.PermissionUtil;
import com.itsense.stock.utils.TreeUtil;
import com.itsense.stock.vo.req.*;
import com.itsense.stock.vo.resp.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 定义用户实现
 */
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;

    /**
     * 生成图片验证码
     * @return
     */
    @Override
    public R<Map> getCaptchaCode() {
        //1.生成图片验证码
        /*
        参数1: 图片的宽度
        参数2: 图片高度
        参数3: 图片中包含验证码的长度
        参数4: 干扰线的数量
         */
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //设置校验码的颜色
        captcha.setBackground(Color.LIGHT_GRAY);
        //获取验证码
        String checkCode = captcha.getCode();
        //获取经过base64的编码处理的图片数据
        String imageData = captcha.getImageBase64();
        //2.生成SessionID(转化为String类型,避免前端精度丢失)
        String sessionId = String.valueOf(idWorker.nextId());
        log.info("当前生成的图片检验码:{},会话id:{}",checkCode,sessionId);
        //3.将SessionId作为key,校验码作为value保存在redis中(使用redis模拟session的行为,通过过期时间设置)
        redisTemplate.opsForValue().set(StockConstant.CHECK_PREFIX + sessionId, checkCode, 5, TimeUnit.MINUTES);
        //组装数据
        Map<String, String> data = new HashMap();
        data.put("imageData",imageData);
        data.put("sessionId",sessionId);
        return R.ok(data);
    }

    /**
     * 返回访问权限列表
     * @return
     */
    @Override
    public R<List<SysPermission>> getPermission() {
        List<SysPermission> permissionsData = sysPermissionMapper.getPermission();
        return R.ok(permissionsData);
    }

    /**
     * 返回查看权限树
     * @return
     */
    @Override
    public R<List<HashMap>> getPermissionTree() {
        //获取全部权限信息
        List<PermissionTreeDomain> permission_data = sysPermissionMapper.getPermissionTree();
        //组装数据进行封装
        HashMap<Long, PermissionTreeDomain> data = new HashMap<>();

        for (PermissionTreeDomain permissionDatum : permission_data) {
            Long id = permissionDatum.getId();
            HashMap<Long, PermissionTreeDomain> map = new HashMap<>();
            map.put(id, permissionDatum);
            data.put(id, permissionDatum);
        }
        //进行递归
        ArrayList<HashMap> treeList = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<>();
        map.put("id",0);
        map.put("title","顶级菜单");
        map.put("level",0);
        treeList.add(map);
        TreeUtil.buildPermissionTree(data, Long.valueOf(0),1, treeList);

        return R.ok(treeList);
    }

    /**
     * 添加权限管理用户
     * @param permissionPostDomain
     * @return
     */
    @Override
    public R<String> addPermission(PermissionPostDomain permissionPostDomain) {
        long nextId = idWorker.nextId();
        SysPermission sysPermission = new SysPermission();
        BeanUtils.copyProperties(permissionPostDomain, sysPermission);
        sysPermission.setId(String.valueOf(nextId));
        sysPermissionMapper.insert(sysPermission);
        return R.ok("操作成功");
    }

    @Override
    public R<String> updatePermission(PermissionUpdateVo vo) {
        SysPermission sysPermission = new SysPermission();
        BeanUtils.copyProperties(vo, sysPermission);
        sysPermissionMapper.updateByPrimaryKey(sysPermission);
        return R.ok("更新成功");
    }

    /**
     * 通过id删除对应的权限用户
     * @param permissionId
     * @return
     */
    @Override
    public R<String> deletePermission(Long permissionId) {
        sysPermissionMapper.deleteByPrimaryKey(permissionId);
        return R.ok("删除成功");
    }

    @Override
    public R<PageResult<SysUserDomain>> getUserByPage(GetUserReqVo vo) {
        //设置分页参数PageHelp
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        //调用mapper查询数据
        List<SysUserDomain> pageData = sysUserMapper.getUserByPage(vo.getUsername(),vo.getNickName(),vo.getStartTime(),vo.getEndTime());
        //组装PageResult对象
        PageInfo<SysUserDomain> pageInfo = new PageInfo<>(pageData);
        PageResult<SysUserDomain> pageResult = new PageResult<>(pageInfo);
        //响应数据
        return R.ok(pageResult);
    }

    @Override
    public R addUser(UserReqVo vo) {
        SysUser user = new SysUser();
        SysUser entity = user.builder()
                .id(String.valueOf(idWorker.nextId()))
                .username(vo.getUserName())
                .password(passwordEncoder.encode(vo.getPassword()))
                .phone(vo.getPhone())
                .email(vo.getEmail())
                .nickName(vo.getNickName())
                .realName(vo.getRealName())
                .sex(vo.getSex())
                .createWhere(vo.getCreateWhere())
                .status(vo.getStatus())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        //调用mapper进行添加
        int count = sysUserMapper.insert(entity);
        //响应数据
        if (count < 0) {
            return R.error("插入失败");
        }else{
            return R.ok("插入成功");
        }
    }

    @Override
    public R<Map<String, List>> getUserRole(String userId) {
        //调用Mapper根据用户id查询用户拥有的角色信息
        List<String> ownRoleIds = sysUserRoleMapper.selectByUserId(userId);
        //查询所有角色信息
        List<SysRole> allRole = sysRoleMapper.selectAllRoles();
        //组装数据
        HashMap<String, List> data = new HashMap<>();
        data.put("ownRoleIds", ownRoleIds);
        data.put("allRoleIds", allRole);
        //响应数据
        return R.ok(data);
    }

    @Override
    public R addUserRoles(AddUserRolesReqVo vo) {
        List<SysUserRole> entities = new ArrayList<>();
        Long userId = Long.valueOf(vo.getUserId());
        for (String roleId : vo.getRoleIds()) {
            entities.add(new SysUserRole(idWorker.nextId(), userId, Long.valueOf(roleId),new Date()));
        }
        //调用mapper更新数据
        int count = sysUserRoleMapper.insertRoles(entities);
        if (count > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }

    @Override
    public R deleteUser(List<Long> ids) {
        int count = sysUserMapper.deleteUser(ids);
        if (count > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }

    @Override
    public R<SysUserSelectDomain> findInfoByUserId(String userId) {
        SysUserSelectDomain sysUser = sysUserMapper.selectByUserId(userId);
        return R.ok(sysUser);
    }

    @Override
    public R updateByUserId(UpdateUserReqVo vo) {
        SysUserUpdateDomain updateDomain = new SysUserUpdateDomain();
        BeanUtils.copyProperties(vo, updateDomain);
        int count = sysUserMapper.updateUserByUserId(updateDomain);
        if (count > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }

    /**
     * 查询角色分页信息
     * @param vo
     * @return
     */
    @Override
    public R<PageResult<SysRole>> getRole(GetRoleReqVo vo) {
        //设置分页参数
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        //查询数据
        List<SysRole> pageData =  sysRoleMapper.getRole();
        //组装pageResult对象
        PageInfo<SysRole> pageInfo = new PageInfo<>(pageData);
        PageResult<SysRole> pageResult = new PageResult<>(pageInfo);
        //响应数据
        return R.ok(pageResult);
    }

    @Override
    public R<List<PermissionsSelectAllDomain>> getPermissionsTreeAll() {
        // 1 调用Mapper查询数据
        List<SysPermission> entitys = sysPermissionMapper.selectAll();
        // 2 组装数据
        // 2.1 获取一级权限集合
        List<PermissionsSelectAllDomain> permissionsSelectAllDomains = new ArrayList<>();
        // 2.2 遍历一级权限集合,获取二级权限集合
        for (SysPermission entity : entitys) {
            // 2.3 权限是否为根节点
            if (entity.getPid()==0){
                // 创建权限对象
                PermissionsSelectAllDomain permissionsSelectAllDomain = new PermissionsSelectAllDomain();
                // 组装数据
                permissionsSelectAllDomain = permissionsSelectAllDomain.builder()
                        .id(String.valueOf(entity.getId()))
                        .title(entity.getTitle())
                        .icon(entity.getIcon())
                        .path(entity.getUrl())
                        .name(entity.getName())
                        .build();
                // 获取权限子权限集合
                List<PermissionsSelectAllDomain>children = PermissionUtil.getChildrenPermissions(entity.getId(),entitys);
                permissionsSelectAllDomain.setChildren(children);
                // 添加到一级权限集合中
                permissionsSelectAllDomains.add(permissionsSelectAllDomain);
            }
        }
        // 3 响应数据
        return R.ok(permissionsSelectAllDomains);
    }

    /**
     * 添加用户权限
     * @param vo
     * @return
     */
    @Override
    public R addRole(AddRoleReqVo vo) {
        //构建sysRole对象
        SysRole sysRole = new SysRole();
        long id = idWorker.nextId();
        sysRole = sysRole.builder()
                .id(String.valueOf(id))
                .name(vo.getName())
                .description(vo.getDescription())
                .status(1)
                .createTime(new Date())
                .updateTime(new Date())
                .deleted(1)
                .build();
        //mapper往sys_role中插入数据
        int count = sysRoleMapper.insertRole(sysRole);
        //创建sysRolePermission对象
        ArrayList<SysRolePermission> entities = new ArrayList<>();
        for (String permissionId : vo.getPermissionIds()) {
            entities.add(SysRolePermission.builder()
                    .id(idWorker.nextId())
                    .roleId(id)
                    .permissionId(Long.valueOf(permissionId))
                    .createTime(new Date())
                    .build());
        }
        //调用mapper往sys_role中插入数据
        int countRolePermission = sysRolePermissionMapper.insertRolePermission(entities);
        if (countRolePermission > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }

    @Override
    public R<List<String>> getRolePermission(String roleId) {
        List<String> data = sysRolePermissionMapper.getRolePermissions(roleId);
        return R.ok(data);
    }

    /**
     * 添加相关角色和角色权限
     * @param vo
     * @return
     */
    @Override
    public R updateRolePermission(UpdateRolePermissionReqVo vo) {
        //调用SysRoleMapper更新数据
        int count = sysRoleMapper.updateRole(vo.getId(), vo.getName(), vo.getDescription(), new Date());
        //调用Mapper更新数据
        ArrayList<SysRolePermission> sysRolePermissions = new ArrayList<>();
        for (String permissionsId : vo.getPermissionsIds()) {
            sysRolePermissions.add(SysRolePermission.builder()
                    .id(idWorker.nextId())
                    .roleId(Long.valueOf(permissionsId))
                    .createTime(new Date())
                    .build());
        }
        int countRolePermission = sysRolePermissionMapper.insertRolePermission(sysRolePermissions);
        if (countRolePermission > 0 && count > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }

    @Override
    public R deleteRole(String roleId) {
        int roleCount = sysRoleMapper.deleteRoleByRoleId(Long.valueOf(roleId));
        if (roleCount > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }

    /**
     * 更新用户数据
     * @param roleId
     * @param status
     * @return
     */
    @Override
    public R updateRoleStatus(String roleId, String status) {
        int roleCount = sysRoleMapper.updateRoleStatus(roleId, status);
        if (roleCount > 0) {
            return R.ok("操作成功");
        }else{
            return R.error("操作失败");
        }
    }


    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 根据用户名返回信息
     * @param userName
     * @return
     */
    @Override
    public SysUser findByUserName(String userName) {
        return sysUserMapper.findUserInfoByUserName(userName);
    }

    @Override
    public R<LoginRespVo> login(LoginReqVo vo) {
        //1.判断参数是否合法
        if(vo == null || StringUtils.isBlank(vo.getUsername()) || StringUtils.isBlank(vo.getPassword()) || StringUtils.isBlank(vo.getCode())){
            return R.error(ResponseCode.DATA_ERROR);
        }
        // 判断验证码以及session是否存在
        if (StringUtils.isBlank(vo.getCode()) || StringUtils.isBlank(vo.getSessionId())) {
            return R.error(ResponseCode.CHECK_CODE_NOT_EMPTY.getMessage());
        }
        // 检验验证码是否正确
        String redisCode = (String) redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX +  vo.getSessionId());
        if (StringUtils.isBlank(redisCode)) {
            return R.error(ResponseCode.CHECK_CODE_TIMEOUT.getMessage());
        }
        //判断验证码是否正确
        if (!redisCode.equalsIgnoreCase(vo.getCode())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR.getMessage());
        }

        //2.根据用户名去数据库查找用户信息，获取密码的密文
        SysUser dbUser = sysUserMapper.findUserInfoByUserName(vo.getUsername());
        if (dbUser == null) {
            //用户不存在
            return R.error(ResponseCode.ACCOUNT_NOT_EXISTS);
        }
        //3.使用密码匹配器判断是否对应密码和用户名
        if (! passwordEncoder.matches(vo.getPassword(), dbUser.getPassword())) {
            //密码不匹配
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }
        //4.响应
        LoginRespVo respVo = new LoginRespVo();
        //应为respVo的数据与dbUser的数据名称和类型一致
        //使用这个方法要保证两个对象的数据类型和名称一致
        BeanUtils.copyProperties(dbUser, respVo);

        //获取用户ID
        String id = dbUser.getId();

        //查询获取主要权限
        List<Map<String, Object>> menuData = sysPermissionMapper.getLoginMenu(id);

        ArrayList<UserLoginMenuDomain> userLoginMenus = new ArrayList<>();

        //permissions
        ArrayList<String> permissions = new ArrayList<>();

        // 获取所有的数据集对象
        HashMap<Long, UserLoginMenuDomain> menusDomainHashMap = new HashMap<Long, UserLoginMenuDomain>();

        //获取对应的岗位
        ArrayList<UserLoginMenuDomain> zeroData = new ArrayList<>();
        for (Map<String, Object> item : menuData) {
            Long pid = (Long) item.get("pid");
            Long user_id = (Long) item.get("id");
            String title = (String) item.get("title");
            String path = (String) item.get("path");
            String icon = (String) item.get("icon");
            String name = (String) item.get("name");
            String code = (String) item.get("code");
            if (!StringUtils.isBlank(code)) {
                permissions.add(code);
            }
            UserLoginMenuDomain userLoginMenusDomain = new UserLoginMenuDomain();
            userLoginMenusDomain.setId(user_id);
            userLoginMenusDomain.setTitle(title);
            userLoginMenusDomain.setPath(path);
            userLoginMenusDomain.setIcon(icon);
            userLoginMenusDomain.setName(name);
            userLoginMenusDomain.setChildren(new ArrayList());
            menusDomainHashMap.put(user_id, userLoginMenusDomain);
            if (pid == 0) {
                zeroData.add(userLoginMenusDomain);
            }
        }

        //用于快速查找子菜单的映射
        HashMap<Long, List<UserLoginMenuDomain>> childrenMap = new HashMap<>();

        //构建一个映射
        for (Map<String, Object> menuDatum : menuData) {
            Long pid = (Long) menuDatum.get("pid");
            Long id1 = (Long) menuDatum.get("id");

            //从数据集中查询获取该循环的对象
            UserLoginMenuDomain domain = menusDomainHashMap.get(id1);
            if (domain != null) {
                //创建一个映射菜单 --> pid : List<pid对应的父对象>
                childrenMap.computeIfAbsent(pid, k -> new ArrayList<>()).add(domain);
            }
        }

        // 假设menuDomainHashMap 已经根据菜单项的ID填充了 UserLoginMenuDomain 对象
        for (UserLoginMenuDomain zeroDatum : zeroData) {
            Long parentId = zeroDatum.getId();
            ArrayList<UserLoginMenuDomain> childrenList = new ArrayList<>();

            //现在开始找到每个主菜单项的子菜单
            if (childrenMap.containsKey(parentId)) {
                List<UserLoginMenuDomain> directChildren = childrenMap.get(parentId);
                for (UserLoginMenuDomain child : directChildren) {
                    //递归为每一个子菜单设置其子菜单(如果存在的话)
                    List<UserLoginMenuDomain> grandChildren = childrenMap.getOrDefault(child.getId(), new ArrayList<>());
                    child.setChildren(grandChildren);
                }
                childrenList.addAll(directChildren);
            }
            zeroDatum.setChildren(childrenList);
        }

        respVo.setMenus(zeroData);
        respVo.setPermissions(permissions);

        //后面数据库操作实现
        return R.ok(respVo);
    }
}
